package com.sedric.base.repository;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.sv.generic.SqlMapSpace;
import com.sv.utils.MybatisSqlSessionFactory;
import com.sv.utils.SqlMapClientFactory;

@Repository
public class BaseRepository<T, U> implements IRepository<T, U> {

	private static final String COUNT_BY_EXAMPLE = ".countByExample";

	private static final String DELETE_BY_EXAMPLE = ".deleteByExample";

	private static final String DELETE_BY_PRIMARYKEY = ".deleteByPrimaryKey";

	private static final String INSERT = ".insert";

	// private static final String INSERT_SELECTIVE =
	// ".insertSelective";

	private static final String SELECT_BY_EXAMPLE = ".selectByExample";

	private static final String SELECT_BY_PRIMARYKEY = ".selectByPrimaryKey";

	private static final String UPDATE_BY_EXAMPLESELECTIVE = ".updateByExampleSelective";

	// private static final String UPDATE_BY_EXAMPLE =
	// ".updateByExample";

	private static final String UPDATE_BY_PRIMARYKEYSELECTIVE = ".updateByPrimaryKeySelective";

	// private static final String UPDATE_BY_PRIMARYKEY =
	// ".updateByPrimaryKey";
	//
	// private static final String SELECT_BY_EXAMPLE_WITHBLOBS =
	// ".selectByExampleWithBLOBs";

	@Autowired
	@Qualifier("sqlSession")
	private SqlSessionTemplate sqlMapClient;

	public int countByExample(U u) throws SQLException {
		return (Integer) sqlMapClient.selectOne(getSqlMapNameSpaceByExample(u)
				+ COUNT_BY_EXAMPLE, u);
	}

	public int deleteByExample(U u) throws SQLException {
		return sqlMapClient.delete(getSqlMapNameSpaceByExample(u)
				+ DELETE_BY_EXAMPLE, u);
	}

	public int deleteByPrimaryKey(T t) throws SQLException {
		return sqlMapClient.delete(
				getSqlMapNameSpace(t) + DELETE_BY_PRIMARYKEY, t);
	}

	public void insert(T t) throws SQLException {
		MybatisSqlSessionFactory.getSqlSession().insert(
				getSqlMapNameSpace(t) + INSERT, t);

	}

	public void insertSelective(T t) throws SQLException {
		sqlMapClient.insert(getSqlMapNameSpace(t), t);
	}

	@SuppressWarnings("unchecked")
	public List<T> selectByExample(U u) throws SQLException {
		return (List<T>) sqlMapClient.selectList(getSqlMapNameSpaceByExample(u)
				+ SELECT_BY_EXAMPLE, u);
	}

	@SuppressWarnings("unchecked")
	public T selectByPrimaryKey(T t) throws SQLException {
		return ((T) sqlMapClient.selectOne(getSqlMapNameSpace(t)
				+ SELECT_BY_PRIMARYKEY, t));
	}

	public int updateByExampleSelective(T t,U u) throws SQLException {

		Map<String,Object> map = new HashMap<String,Object>();
		map.put("record", t);
		map.put("example", u);
		return sqlMapClient.update(getSqlMapNameSpaceByExample(u)
				+ UPDATE_BY_EXAMPLESELECTIVE, map);
	}
	
	public int  updateByExample(T t,U u) throws SQLException{
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("record", t);
		map.put("example", u);
		return sqlMapClient.update(getSqlMapNameSpaceByExample(u)
				+ UPDATE_BY_EXAMPLESELECTIVE, map);
	}

	public int updateByPrimaryKey(T t) throws SQLException {
		return sqlMapClient.update(getSqlMapNameSpace(t)
				+ UPDATE_BY_PRIMARYKEYSELECTIVE, t);
	}
	
	public int updateByPrimaryKeySelective(T t) throws SQLException {

		return sqlMapClient.update(getSqlMapNameSpace(t)
				+ UPDATE_BY_PRIMARYKEYSELECTIVE, t);
	}

	public SqlSessionTemplate getSqlMapClient() {
		return sqlMapClient;
	}

	public void setSqlMapClient(SqlSessionTemplate sqlMapClient) {
		this.sqlMapClient = sqlMapClient;
	}

	private String getSqlMapNameSpace(T t) {
		SqlMapSpace sqlMap = t.getClass().getSuperclass()
				.getAnnotation(SqlMapSpace.class);
		if (sqlMap == null) {
			sqlMap = t.getClass().getAnnotation(SqlMapSpace.class);
		}
		return sqlMap.name();
	}

	private String getSqlMapNameSpaceByExample(U u) {
		SqlMapSpace sqlMap = u.getClass().getSuperclass()
				.getAnnotation(SqlMapSpace.class);
		if (sqlMap == null) {
			sqlMap = u.getClass().getAnnotation(SqlMapSpace.class);
		}
		return sqlMap.name();
	}

}
